KMP算法:求next数组,一听就会 您所在的位置:网站首页 kmp 求next KMP算法:求next数组,一听就会

KMP算法:求next数组,一听就会

2023-08-27 09:47| 来源: 网络整理| 查看: 265

KMP算法是啥?

KMP算法就是一种字符串匹配算法,简单说就是从一个长字符串中搜索一个短字符串(也叫模式串)。 这个算法我从大学上数据结构课第一次学到,到现在反反复复学过不下十次,每次都当时觉得懂了,可就是记不住,相信很多人也有同感。最记不住的地方就是next数组的求法。 今天我尝试着用尽量容易理解的方法去讲解这个问题,希望我自己和各位读者从此把这个算法牢牢记住。

算法概述

前面的引子就不说了,KMP算法的关键在于next数组。next数组的作用是:匹配到某一位失败时,回退到next[i]这一位重新去匹配。

我定义了一个名词:端长

我这里自己定义一个名词“端长”,指的是字符串前缀和后缀相等的长度。比如字符串"ababa"的端长有3,1。因为前三位aba与后三位aba相等,长度为3,所以端长为3。第一位与最后一位也相同,所以1也是一个端长,但最大端长是3。 请记住这个“端长”的含义。我尝试过很多次去解释kmp算法的实现,发现这里必须有一个定义,才便于后面的描述和理解。

实际上,求next[i]的值就是求模式串第i个字符之前(不包括第i个)的子串的最大端长。 例如:模式串为ababacd,next[5]就是ababa这个字符串的最大端长,也就是3,所以next[5] = 3。

手动构造next数组

手动构造next数组的方法:前两位固定为-1和0,第三位,下标i=2,next[i] 的值为模式串p的前2位子串的最大端长,以此类推。对于手动构造,最大端长的值可以一眼看出来。

代码求next数组

问题在于,对于一个字符串,最大端长的值用代码怎么求?暴力法当然可以,但太慢了,每一次都需要O(n)的时间复杂度,而我们现在需要求len(p)个字串的最大端长,这样的复杂度太高了。 关键点在这里:我们可以用递推的方法来求最大端长。求next数组的时候,我们是从0开始从前往后算的。对于next[i]的值,我们可以利用next[i-1]的值来计算。

递推求端长

要确定这样一个前提:如果一个字符串p的最大端长为k,那么这个字符串后面再加一位之后,最大端长最多只能是k+1,这是上限。而且要等于k+1还有个前提,就是加的这一个字符等于p[k]。 例如:字符串ababa的最大端长为3,如果在后面加一个b,ababab,则最大端长变为4,因为p[3]是b。

下面开始递推:假如next[i-1]的值为k,也就是模式串p的0到i-2位的最大端长为k,那么如果p[k] == p[i-1],则可以得到结果:p的0到i-1为的最大端长为k+1,next[i] = k+1。

那如果p[k] != p[i-1]呢?可以继续寻找小一点的端长,这恰好是0到k-1字串的最大端长,把这个端长设为新的k,重复上面的步骤。

例如:如果要求ababaa的最大端长,先看去掉最后一位之后 ababa的最大端长是3,对应前缀是aba。但最后一位p[5]是a, 而p[3]是b,不相等。继续寻找ababa的下一个端长,其实也就是aba的最大端长1,正好p[1]是a,等于最后一位p[5],所以ababaa的最大端长就是1。

这部分逻辑转化成Go语言代码就是这样:

for i:= 1; i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有